package run.halo.app.controller.admin.api;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import run.halo.app.config.WxMaConfiguration;
import run.halo.app.exception.BadRequestException;
import run.halo.app.model.app.WxEncrypted;
import run.halo.app.model.app.WxLoginInfo;
import run.halo.app.model.app.WxUserEncrypted;
import run.halo.app.model.app.WxUserInfo;
import run.halo.app.model.dto.UserDTO;
import run.halo.app.model.entity.User;
import run.halo.app.model.enums.MFAType;
import run.halo.app.model.params.LoginParam;
import run.halo.app.security.token.AuthToken;
import run.halo.app.service.AdminService;
import run.halo.app.service.UserService;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import me.chanjar.weixin.common.error.WxErrorException;

import run.halo.app.utils.JsonUtils;

import java.util.Date;

@Slf4j
@RestController
@RequestMapping("/api/mini/{appid}")
public class MiniAppController {
    private final UserService userService;
    private final AdminService adminService;

    public MiniAppController(UserService userService, AdminService adminService) {
        this.userService = userService;
        this.adminService = adminService;
    }


    /**
     * 登陆接口
     */
    @GetMapping("/login")
    public UserDTO login(@PathVariable String appid, String code) {
        if (StringUtils.isBlank(code)) {
            throw new BadRequestException("empty jscode");
           // return R.failed("empty jscode");
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        WxMaJscode2SessionResult session=getSessionKey(code,wxService);
        if (session!=null){
            User user=getAppUser(session.getOpenid());
            UserDTO userDTO=new UserDTO().convertFrom(user);
            userDTO.setSession_key(session.getSessionKey());
            userDTO.setUnionid(session.getUnionid());
            return userDTO;
            //return R.ok(appUser);
        }
        else {
            throw new BadRequestException("获取用户session异常");
        }
       // return R.failed("获取用户session异常");
    }

    private WxMaJscode2SessionResult getSessionKey(String code,WxMaService wxService) {
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            //log.info(session.getSessionKey());
            // log.info(session.getOpenid());
            log.info("login____session：" + session );
            return session;
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    private User getAppUser(String openid)  {
        User appUser=new User();
         appUser.setOpenid(openid);
         User user=userService.getByOpenidOfNonNull(openid);
        if(user != null){
            log.info("》》》AppUser为：" +JsonUtils.toJson(user) );
            return user;
        }
        return appUser;
    }

    /**
     * <pre>
     * 获取用户信息接口
     * </pre>
     */
    @PostMapping("/info")
    public UserDTO info(@PathVariable String appid,@RequestBody WxLoginInfo loginInfo) {
        if (StringUtils.isBlank(loginInfo.getCode())) {
           // return R.failed("empty jscode");
            throw new BadRequestException("empty jscode");
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        String sessionKey="";
        WxMaJscode2SessionResult session=getSessionKey(loginInfo.getCode(),wxService);
        if (session==null){
            throw new BadRequestException("获取用户session异常");
           // return R.failed("获取用户session异常");
        }
        sessionKey=session.getSessionKey();
        // 用户信息校验
        WxUserEncrypted user=loginInfo.getWxUser();
        if (!wxService.getUserService().checkUserInfo(sessionKey, user.getRawData(), user.getSignature())) {
            throw new BadRequestException("user check failed");
            //return R.failed("user check failed");//return "user check failed";
        }
        // 解密用户信息
        WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(sessionKey, user.getEncryptedData(), user.getIv());
        log.info("》解密用户信息：" +userInfo );
        return getUserInfo(userInfo,appid,sessionKey);
        //return R.ok(userInfo);
    }

    private UserDTO getUserInfo(WxMaUserInfo userInfo,String appid,String sessionkey) {
        return getUserInfo(userInfo,appid,sessionkey,null);
    }
    private UserDTO getUserInfo(WxMaUserInfo userInfo,String appid,String sessionkey,String phone) {
        String openid=userInfo.getOpenId();
        log.info("》openid用户信息：" +openid +" info:"+userInfo);
        User appUser=new User();
        appUser.setOpenid(openid);
        User appUser2=userService.getByOpenidOfNonNull(openid);
       // User appUser2=userService.getByUsernameOfNonNull(openid);
       // String token=getUUID();
        appUser.setOpenid(openid);
       // appUser.setUnionid(userInfo.getUnionId());
        appUser.setAppid(appid);
        appUser.setUsername(openid);
        if (phone!=null) {
            appUser.setPhone(phone);
            appUser.setUsername(phone);
        }
        appUser.setCity(userInfo.getCity());
        appUser.setAvatar(userInfo.getAvatarUrl());
       // appUser.setCountry(userInfo.getCountry());
        appUser.setNickname(userInfo.getNickName());
        appUser.setSex(userInfo.getGender());
       // appUser.setLanguage(userInfo.getLanguage());
        appUser.setProvince(userInfo.getProvince());
       // appUser.setToken(token);
        appUser.setUpdateTime(new Date());
        if (appUser2==null) {
            appUser.setPassword("12345678");
            appUser.setMfaType(MFAType.NONE);
            appUser.setDescription("合理合法维权");
            //appUser.setCreateTime(new Date());
            userService.setPassword(appUser,"12345678");
            appUser=userService.create(appUser);
          //  appUserService.save(appUser);
        }
        else {
            appUser.setId(appUser2.getId());
            appUser.setMfaType(appUser2.getMfaType());
            appUser.setPassword(appUser2.getPassword());
            appUser.setCreateTime(appUser2.getCreateTime());
            if (appUser2.getPhone()!=null) {
                appUser.setPhone(appUser2.getPhone());
            }
            appUser.setDescription(appUser2.getDescription());
            userService.update(appUser);
           // appUserService.updateById(appUser);
        }
        UserDTO userDTO=new UserDTO().convertFrom(appUser);
        userDTO.setSession_key(sessionkey);
        userDTO.setUnionid(userInfo.getUnionId());
      //  appUser.setSession_key(sessionkey);
      //  return R.ok(appUser);
        if (appUser.getUsername()!=null) {
            LoginParam loginParam = new LoginParam();
            loginParam.setUsername(appUser.getUsername());
            loginParam.setPassword("12345678");
            AuthToken token = adminService.authCodeCheck(loginParam);

            userDTO.setAccessToken(token.getAccessToken());
            userDTO.setExpiredIn(token.getExpiredIn());
            userDTO.setRefreshToken(token.getRefreshToken());
        }
        return userDTO;
    }

    @PostMapping("/phone")
    public UserDTO phone(@PathVariable String appid,@RequestBody WxEncrypted wxEncrypted) {
       // log.info("》》》wxEncrypted为：" + JsonUtils.toJson(wxEncrypted));
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(wxEncrypted.getSession_key(), wxEncrypted.getEncryptedData(), wxEncrypted.getIv());
        log.info("》》》解密 PhoneVO为：" +phoneNoInfo );
        return getUserPhoneInfo(wxEncrypted,appid,phoneNoInfo.getPhoneNumber());
    }

    private UserDTO getUserPhoneInfo(WxEncrypted wxEncrypted,String appid,String phoneNumber) {
        String sessionkey=wxEncrypted.getSession_key();
        WxMaUserInfo userInfo=new WxMaUserInfo();
        userInfo.setOpenId(wxEncrypted.getOpenid());
        userInfo.setUnionId(wxEncrypted.getUnionid());
        WxUserInfo wxUser=wxEncrypted.getUserInfo();
        if (wxUser!=null) {
            userInfo.setCity(wxUser.getCity());
            userInfo.setAvatarUrl(wxUser.getAvatarUrl());
            userInfo.setCountry(wxUser.getCountry());
            userInfo.setNickName(wxUser.getNickName());
            userInfo.setGender(wxUser.getGender().toString());
            userInfo.setLanguage(wxUser.getLanguage());
            userInfo.setProvince(wxUser.getProvince());
        }
        return getUserInfo(userInfo,appid,sessionkey,phoneNumber);
    }

    @PostMapping("/openid")
    public UserDTO openid(@PathVariable String appid,@RequestBody WxEncrypted wxEncrypted) {
         log.info("》》》openid：" + wxEncrypted);
         return getUserPhoneInfo(wxEncrypted,appid,"");
    }
}
